#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <unistd.h>

#define NUM 5
int tickets=1000;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //初始化锁

//这是初始化线程名的类
class threadData
{
public:
    threadData(int id)
    {
        threadname="thread "+std::to_string(id);
    }

    std::string threadname;
};

//转换为16进制
std::string toHex(pthread_t tid)
{
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "0x%x", tid);
    return buffer;
}

//模拟抢票的函数
void *getTickets(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    std::string tid=toHex(pthread_self());

    while(true)
    {
        pthread_mutex_lock(&lock); // 申请锁成功，才能往后执行，不成功，阻塞等待
        if(tickets>0)
        {
            printf("%s %s, get a ticket: %d\n",td->threadname.c_str(),tid.c_str(),tickets);
            tickets--;
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
        //没有等待的话，只有一个线程在抢票
        usleep(10); //模拟抢了票之后现场进行的操作，进行一点等待
    }

    printf("%s %s ... quit\n", td->threadname.c_str(),tid.c_str());
    return nullptr;
}

//使用多线程模拟抢票过程
void test1()
{
    //创建多线程
    std::vector<pthread_t> threads;
    for(int i=1;i<=NUM;i++)
    {
        pthread_t tid;
        threadData *td=new threadData(i);
        
        pthread_create(&tid,nullptr,getTickets,(void*)td);
        threads.push_back(tid);
        usleep(1000);
    }

    //销毁线程资源
    for(auto thread:threads)
    {
        pthread_join(thread,nullptr);
    }
}

int main()
{
    test1();
    return 0;
}